package com.compass.network.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.compass.framework.ext.toJson
import com.compass.framework.manager.UserInfoManager
import com.compass.framework.model.PatientInfo
import com.compass.framework.utils.LogUtil
import com.compass.network.callback.IApiErrorCallback
import com.compass.network.error.ApiException
import com.compass.network.error.ERROR
import com.compass.network.error.ExceptionHandler
import com.compass.network.flow.requestFlow

import com.compass.network.response.BaseResponse
import com.netease.nimlib.sdk.NIMClient
import com.netease.nimlib.sdk.auth.AuthService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout

/**
 * @desc   viewModel基类
 */
open class BaseViewModel : ViewModel() {

    private var limitedCall: Int = 0

    /**
     * 不依赖BaseRepository，运行在主线程中，可直接调用
     * @param errorCall 错误回调
     * @param responseBlock 请求函数
     * @param successBlock 请求回调
     */
    fun <T> launchUIWithResult(
        responseBlock: suspend () -> BaseResponse<T>?,
        errorCall: IApiErrorCallback?,
        successBlock: (T?) -> Unit
    ) {
        launchFlow(errorCall,responseBlock,successBlock)
//        viewModelScope.launch(Dispatchers.Main) {
//            val result = safeApiCallWithResult(errorCall = errorCall, responseBlock)
//            successBlock(result)
//
//
//        }
    }

    /**
     * 不依赖BaseRepository，需要在作用域中运行
     * @param errorCall 错误回调
     * @param responseBlock 请求函数
     */
    private suspend fun <T> safeApiCallWithResult(
        errorCall: IApiErrorCallback?,
        responseBlock: suspend () -> BaseResponse<T>?
    ): T? {
        try {
            val response = withContext(Dispatchers.IO) {
                responseBlock()
            } ?: return null

            if (response.isFailed()) {
                response.msg?.let {
                    throw ApiException(response.code, it)
                }?:kotlin.run {
                    throw ApiException(response.code, ERROR.NOT_FOUND.errMsg)
                }

            }
            return response.data
        } catch (e: Exception) {
            e.printStackTrace()
            val exception = ExceptionHandler.handleException(e)
            if (ERROR.LOGIN_FAILURE.code == exception.errCode) {
                if (limitedCall < 1) {
                    limitedCall++
                    errorCall?.onLoginFail(exception.errCode, ERROR.LOGIN_FAILURE.errMsg)
                }
            } else {
                errorCall?.onError(exception.errCode, exception.errMsg)
            }
        }
        return null
    }


    /**
     * flow 网络请求 测试
     * @param errorCall 错误回调
     * @param requestCall 请求函数
     * @param loadingBlock 是否展示加载框
     * @param successBlock 请求结果
     */
    private  fun <T> launchFlow(
        errorCall: IApiErrorCallback? = null,
        requestCall: suspend () -> BaseResponse<T>?,
        successBlock: (T?) -> Unit
    ) {
        viewModelScope.launch(Dispatchers.Main) {
            val data = requestFlow(errorBlock = { code, error ->
                if (ERROR.NOT_FOUND.code == code) {
                    errorCall?.onLoginFail(code, error)
                } else {
                    errorCall?.onError(code, error)
                }
            }, requestCall)
            successBlock(data)
        }
    }


}